package com.semidata.trp.algorithm.job;

import com.semidata.rtd.core.http.server.HttpSession;
import com.semidata.rtd.core.json.JsonObject;
import com.semidata.rtd.core.log.Logger;
import com.semidata.rtd.engine.executor.TaskExecutor;
import com.semidata.rtd.engine.job.AbstractJob;
import com.semidata.rtd.engine.job.JobCompleteHandler;
import com.semidata.rtd.engine.job.Task;
import com.semidata.trp.algorithm.compile.TaskCompile;
import com.semidata.trp.algorithm.config.Config;
import com.semidata.trp.algorithm.request.TaskRequest;
import com.semidata.trp.algorithm.run.TaskRun;

public class AlgorithmJob extends AbstractJob{
	private AlgorithmJobContext context;
	public static Exception cause;
	private static class DoneHandler implements JobCompleteHandler {

		private AlgorithmJobContext context;

		public DoneHandler(AlgorithmJobContext context) {
			this.context = context;
		}

		@Override
		public void handle() {
			HttpSession session = context.getHttpSession();
			try {
				System.out.println("has a request");
				JsonObject response = new JsonObject();
				response.putString("message", context.getResult().toString());
				response.putString("log", context.getLog());
				response.putNumber("statusCode", 200);
				session.getResponse().setHeader("Access-Control-Allow-Origin", "*");
				session.getResponse().end(response.toString());
			} catch (Exception e) {
				e.printStackTrace();
				Logger.log("ERROR", "request has been finished ,Error when response result : " + e);
			}
		}

	}

	private static class ErrorHandler implements JobCompleteHandler {

		private AlgorithmJobContext context;

		public ErrorHandler(AlgorithmJobContext context) {
			this.context = context;
		}
		
		@Override
		public void handle() {
			HttpSession session = context.getHttpSession();
			Exception cause = AlgorithmJob.cause;
			try {
				JsonObject response = new JsonObject();
				if (cause.getClass() == InterruptedException.class) {
					response.putString("message", "This algorithm running time is too long, it may affect the performance of decision-servers, optimize it as much as possible!");
				} else {
					response.putString("message", cause.getMessage());
				}
				response.putString("log", context.getLog());
				response.putNumber("statusCode", 300);
				session.getResponse().setHeader("Access-Control-Allow-Origin", "*");
				session.getResponse().end(response.toString());
			} catch (Exception e) {
				Logger.log("ERROR", "request has error, Error when response error : " + e);
			}


		}
	}

	public AlgorithmJob(TaskExecutor executor, AlgorithmJobContext context) {
		super(executor, new DoneHandler(context), new ErrorHandler(context));
		this.context = context;
		AlgorithmJob.cause = null;
	}
	
	
	@Override
	protected void schedule(Task task) {
		TaskExecutor executor = getExecutor();
		if (task == null) {
			TaskRequest requestTask = new TaskRequest(this);
			executor.submit(requestTask);
		} else if (task.getClass() == TaskRequest.class) {
			Exception cause = task.getException();
			if (cause != null) {
				AlgorithmJob.cause = cause;
				error();
			} else {
				TaskCompile compileTask = new TaskCompile(this);
				executor.submit(compileTask);
			}
		} else if (task.getClass() == TaskCompile.class) {
			Exception cause = task.getException();
			if (cause != null) {
				AlgorithmJob.cause = cause;
				error();
			} else {
				TaskRun runTask = new TaskRun(this, Config.getConfig().getRunTimeout());
				executor.submit(runTask);
			}
			
		} else if (task.getClass() == TaskRun.class) {
			Exception cause = task.getException();
			if (cause != null) {
				AlgorithmJob.cause = cause;
				error();
			} else {
				done();
			}
		} else {
			AlgorithmJob.cause = new Exception("unknow error");
			error();
		}
		
	}
	public AlgorithmJobContext getJobContext() {
		return context;
	}


}
